home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol03 / 05 / filter / filter.c < prev    next >
C/C++ Source or Header  |  1988-09-01  |  9KB  |  343 lines

  1. /*** filter.c - Microsoft Editor Filter Extension
  2. *
  3. * Purpose:
  4. *  Provides a new editting function, filter, which replaces its argument with
  5. *  the the argument run through an arbitrary operating system filter program.
  6. *
  7. *************************************************************************/
  8. #define ID    " filter ver 1.00 "##__DATE__##" "##__TIME__
  9.  
  10. #include <stdlib.h>            /* min macro definition     */
  11. #include <string.h>            /* prototypes for string fcns    */
  12. #include "ext.h"
  13.  
  14. /*************************************************************************
  15. *
  16. * Internal function forward declarations
  17. */
  18. flagType pascal      DoSpawn    (char *);
  19. void     pascal      id        (char *);
  20. void     pascal EXTERNAL SetFilter  (char far *);
  21.  
  22. /*************************************************************************
  23. *
  24. * global data
  25. */
  26. PFILE    pFileFilt    = 0;            /* handle for filterfile*/
  27. char    *szNameFilt    = "<filter-file>";    /* name of filter file    */
  28. char    *szTemp1    = "filter1.tmp";    /* name of 1st temp file*/
  29. char    *szTemp2    = "filter2.tmp";    /* name of 2nd temp file*/
  30. char    filtcmd[BUFLEN] = "";            /* filter command itself*/
  31.  
  32. /*** filter - Editor filter extension function
  33. *
  34. * Purpose:
  35. *  Replace seleted text with that text run through an arbitrary filter
  36. *
  37. *  NOARG       - Filter entire current line
  38. *  NULLARG     - Filter current line, from cursor to end of line
  39. *  LINEARG     - Filter range of lines
  40. *  BOXARG      - Filter characters with the selected box
  41. *
  42. *  NUMARG      - Converted to LINEARG before extension is called.
  43. *  MARKARG     - Converted to Appropriate ARG form above before extension is
  44. *         called.
  45. *
  46. *  STREAMARG   - Treated as BOXARG
  47. *
  48. *  TEXTARG     - Set new filter command
  49. *
  50. * Input:
  51. *  Editor Standard Function Parameters
  52. *
  53. * Output:
  54. *  Returns TRUE on success, file updated, else FALSE.
  55. *
  56. *************************************************************************/
  57. flagType pascal EXTERNAL filter (
  58. unsigned int argData,            /* keystroke invoked with    */
  59. ARG far *pArg,                /* argument data        */
  60. flagType fMeta                /* indicates preceded by meta    */
  61. ) {
  62. char    buf[BUFLEN];            /* buffer for lines        */
  63. int    cbLineMax;            /* max lein length in filtered    */
  64. LINE    cLines;             /* count of lines in file    */
  65. LINE    iLineCur;            /* line being read        */
  66. PFILE    pFile;                /* file handle of current file    */
  67. /*
  68. ** Initialize: identify ourselves, get handle to current file, and discard the
  69. ** contents of the filter-file.
  70. */
  71. id ("");
  72. pFile = FileNameToHandle ("", "");
  73. DelFile (pFileFilt);
  74. /*
  75. ** Step 1, based on the argument type, copy the selected region into the
  76. ** (upper left most position of) filter-file.
  77. **
  78. ** Note that TEXTARG is a special case that allows the user to change the name
  79. ** of the filter command to be used.
  80. */
  81. switch (pArg->argType) {
  82.     case NOARG:             /* filter entire line        */
  83.     CopyLine (pFile,
  84.           pFileFilt,
  85.           pArg->arg.noarg.y,
  86.           pArg->arg.noarg.y,
  87.           (LINE) 0);
  88.     break;
  89.  
  90.     case NULLARG:            /* filter to EOL        */
  91.     CopyStream (pFile,
  92.             pFileFilt,
  93.             pArg->arg.nullarg.x,
  94.             pArg->arg.nullarg.y,
  95.             255,
  96.             pArg->arg.nullarg.y,
  97.             (COL) 0,
  98.             (LINE) 0);
  99.     break;
  100.  
  101.     case LINEARG:            /* filter line range        */
  102.     CopyLine (pFile,
  103.           pFileFilt,
  104.           pArg->arg.linearg.yStart,
  105.           pArg->arg.linearg.yEnd,
  106.           (LINE) 0);
  107.     break;
  108.  
  109.     case BOXARG:            /* filter box            */
  110.     CopyBox (pFile,
  111.          pFileFilt,
  112.          pArg->arg.boxarg.xLeft,
  113.          pArg->arg.boxarg.yTop,
  114.          pArg->arg.boxarg.xRight,
  115.          pArg->arg.boxarg.yBottom,
  116.          (COL) 0,
  117.          (LINE) 0);
  118.     break;
  119.  
  120.     case TEXTARG:
  121.     SetFilter (pArg->arg.textarg.pText);
  122.     return 1;
  123.     }
  124. /*
  125. ** Step 2, write the selected text to disk
  126. */
  127. if (!FileWrite (szTemp1, pFileFilt)) {
  128.     id ("** Error writing temporary file **");
  129.     return 0;
  130.     }
  131. /*
  132. ** Step 3, create the command to be executed:
  133. **   user specified filter command + " " + tempname 1 + " >" + tempname 2
  134. ** Then perform the filter operation on that file, creating a second temp file.
  135. */
  136. strcpy (buf,filtcmd);
  137. strcat (buf," ");
  138. strcat (buf,szTemp1);
  139. strcat (buf," >");
  140. strcat (buf,szTemp2);
  141. if (!DoSpawn (buf)) {
  142.     id ("** Error executing filter **");
  143.     return 0;
  144.     }
  145. /*
  146. ** Step 4, delete the contents of the filter-file, and replace it by reading
  147. ** in the contents of that second temp file.
  148. */
  149. DelFile (pFileFilt);
  150. if (!FileRead (szTemp2, pFileFilt)) {
  151.     id ("Error reading temporary file **");
  152.     return 0;
  153.     }
  154. /*
  155. ** Step 5, calculate the maximum width of the data we got back from the
  156. ** filter. Then, based again on the type of region selected by the user,
  157. ** DISCARD the users select region, and copy in the contents of the filter
  158. ** file in an equivelant type.
  159. */
  160. cLines = FileLength (pFileFilt);
  161. cbLineMax = 0;
  162. for (iLineCur = 0; iLineCur < cLines; iLineCur++)
  163.     cbLineMax = max (cbLineMax, GetLine (iLineCur, buf, pFileFilt));
  164.  
  165. switch (pArg->argType) {
  166.     case NOARG:             /* filter entire line        */
  167.     DelLine  (pFile,
  168.           pArg->arg.noarg.y,
  169.           pArg->arg.noarg.y);
  170.     CopyLine (pFileFilt,
  171.           pFile,
  172.           (LINE) 0,
  173.           (LINE) 0,
  174.           pArg->arg.noarg.y);
  175.     break;
  176.  
  177.     case NULLARG:            /* filter to EOL        */
  178.     DelStream  (pFile,
  179.             pArg->arg.nullarg.x,
  180.             pArg->arg.nullarg.y,
  181.             255,
  182.             pArg->arg.nullarg.y);
  183.     CopyStream (pFileFilt,
  184.             pFile,
  185.             (COL) 0,
  186.             (LINE) 0,
  187.             cbLineMax,
  188.             (LINE) 0,
  189.             pArg->arg.nullarg.x,
  190.             pArg->arg.nullarg.y);
  191.     break;
  192.  
  193.     case LINEARG:            /* filter line range        */
  194.     DelLine  (pFile,
  195.           pArg->arg.linearg.yStart,
  196.           pArg->arg.linearg.yEnd);
  197.     CopyLine (pFileFilt,
  198.           pFile,
  199.           (LINE) 0,
  200.           cLines-1,
  201.           pArg->arg.linearg.yStart);
  202.     break;
  203.  
  204.     case BOXARG:            /* filter box            */
  205.     DelBox    (pFile,
  206.          pArg->arg.boxarg.xLeft,
  207.          pArg->arg.boxarg.yTop,
  208.          pArg->arg.boxarg.xRight,
  209.          pArg->arg.boxarg.yBottom);
  210.     CopyBox (pFileFilt,
  211.          pFile,
  212.          (COL) 0,
  213.          (LINE) 0,
  214.          cbLineMax-1,
  215.          cLines-1,
  216.          pArg->arg.boxarg.xLeft,
  217.          pArg->arg.boxarg.yTop);
  218.     break;
  219.     }
  220. /*
  221. ** Clean-up: delete the temporary files we've created
  222. */
  223. strcpy (buf, "DEL ");
  224. strcat (buf, szTemp1);
  225. DoSpawn (buf);
  226. strcpy (buf+4, szTemp2);
  227. DoSpawn (buf);
  228.  
  229. return 1;
  230. /* end filter */}
  231.  
  232. /*** DoSpawn - Execute an OS/2 or DOS command
  233. *
  234. * Purpose:
  235. *  Send the passed strign to OS/2 or DOS for execution.
  236. *
  237. * Input:
  238. *  szCmd    = Command to be executed
  239. *
  240. * Output:
  241. *  Returns TRUE if successfull, else FALSE.
  242. *
  243. *************************************************************************/
  244. flagType pascal DoSpawn (
  245. char    *szCmd
  246. ) {
  247. char   cmd[BUFLEN];
  248.  
  249. strcpy (cmd, "arg \"");
  250. strcat (cmd, szCmd);
  251. strcat (cmd, "\" shell");
  252. return fExecute (cmd);
  253.  
  254. /* end DoSpawn */}
  255.  
  256. /*** SetFilter - Set filter command to be used
  257. *
  258. * Purpose:
  259. *  Save the passed string paramater as the filter command to be used by the
  260. *  filter function. Called either because the "filtcmd:" switch has been
  261. *  set, or because the filter command recieved a TEXTARG.
  262. *
  263. * Input:
  264. *  szCmd    = Pointer to asciiz filter command
  265. *
  266. * Output:
  267. *  Returns nothing. Command saved
  268. *
  269. *************************************************************************/
  270. void pascal EXTERNAL SetFilter (
  271. char far *szCmd
  272. ) {
  273. strcpy (filtcmd,szCmd);
  274. /* end SetFilter */}
  275.  
  276. /*** WhenLoaded - Extension Initialization
  277. *
  278. * Purpose:
  279. *  Executed when extension gets loaded. Identify self, create <filter-file>,
  280. *  and assign default keystroke.
  281. *
  282. * Input:
  283. *  none
  284. *
  285. * Output:
  286. *  Returns nothing. Initializes various data.
  287. *
  288. *************************************************************************/
  289. void WhenLoaded (void) {
  290.  
  291. pFileFilt = FileNameToHandle (szNameFilt,szNameFilt);
  292. if (!pFileFilt) {
  293.     pFileFilt = AddFile (szNameFilt);
  294.     FileRead (szNameFilt, pFileFilt);
  295.     }
  296. SetKey ("filter", "alt+f");
  297. id ("text filter extension:");
  298.  
  299. /* end WhenLoaded */}
  300.  
  301. /*** id - identify extension
  302. *
  303. * Purpose:
  304. *  identify ourselves, along with any passed informative message.
  305. *
  306. * Input:
  307. *  pszMsg    = Pointer to asciiz message, to which the extension name
  308. *          and version are appended prior to display.
  309. *
  310. * Output:
  311. *  Returns nothing. Message displayed.
  312. *
  313. *************************************************************************/
  314. void pascal id (
  315. char *pszFcn                    /* function name    */
  316. ) {
  317. char    buf[BUFLEN];                /* message buffer    */
  318.  
  319. strcpy (buf,pszFcn);
  320. strcat (buf,ID);
  321. DoMessage (buf);
  322. /* end id */}
  323.  
  324. /*************************************************************************
  325. **
  326. ** Switch communication table to the editor.
  327. */
  328. struct swiDesc    swiTable[] = {
  329.     {"filtcmd",     (PIF)(long)(void far *)SetFilter,    SWI_SPECIAL},
  330.     {0, 0, 0}
  331.     };
  332.  
  333. /*************************************************************************
  334. **
  335. ** Command communication table to the editor.
  336. ** Defines the name, location and acceptable argument types.
  337. */
  338.  
  339. struct cmdDesc    cmdTable[] = {
  340.     {"filter",filter,0, KEEPMETA | NOARG | BOXARG | NULLARG | LINEARG | MARKARG | NUMARG | TEXTARG | MODIFIES},
  341.     {0, 0, 0}
  342.     };
  343.